﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lidgren.Network;
using Lidgren.Network.Xna;
using Microsoft.Xna.Framework;
using SharedLib.Engine;

namespace SharedLib.Network.Server
{
    public class ServerListener
    {
        Server server;
        NetServer netserver;
        NetConnection _msgSender;

        public ServerListener(NetServer nets, Server srv)
        {
            server = srv;
            netserver = nets;
        }

        public void Start()
        {
            long last = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond;

            NetIncomingMessage packetin;
            while (true)
            {
                while ((packetin = netserver.ReadMessage()) != null)
                {
                    _msgSender = packetin.SenderConnection;
                    switch (packetin.MessageType)
                    {
                        case NetIncomingMessageType.StatusChanged:
                            {
                                if (_msgSender.Status == NetConnectionStatus.Disconnected)
                                {
                                    server.Console.ConsoleWrite(server.EntitiesManager.GetPlayerByConnection(_msgSender).Name + " Disconnected");
                                    server.ServerSender.SendEntityLeft(server.EntitiesManager.GetPlayerByConnection(_msgSender));
                                    server.EntitiesManager.RemovePlayer(server.EntitiesManager.GetPlayerByConnection(_msgSender));
                                }
                                break;
                            }
                        case NetIncomingMessageType.ConnectionApproval:
                            {
                                int authcode = packetin.ReadInt32();
                                string name = packetin.ReadString();
                                ServerPlayer dummy = new ServerPlayer(_msgSender);
                                dummy.Name = name;

                                dummy.HP = Constants.Random.Next(50, 101);
                                dummy.HPMAX = 100;
                                dummy.Mana = Constants.Random.Next(50, 101);
                                dummy.ManaMAX = 100;

                                server.EntitiesManager.AddEntity(dummy);
                                _msgSender.Approve();
                                server.GameWorld.GenerateSpawnPosition(server.EntitiesManager.GetPlayerByConnection(_msgSender));
                                //server.ServerSender.SendPlayerChunk(server.EntitiesManager.GetPlayerByConnection(_msgSender));
                                server.ServerSender.SendInitialUpdate(server.EntitiesManager.GetPlayerByConnection(_msgSender));
                                //server.ServerSender.SendEntityJoined(server.EntitiesManager.GetPlayerByConnection(_msgSender));
                                server.Console.ConsoleWrite(name + " Connected");
                                break;
                            }
                        case NetIncomingMessageType.Data:
                            {
                                SharedLib.Constants.PacketType dataType = (SharedLib.Constants.PacketType)packetin.ReadByte();

                                switch (dataType)
                                {
                                    case SharedLib.Constants.PacketType.EntityMovementUpdate:
                                        {
                                            ServerPlayer p = server.EntitiesManager.GetPlayerByConnection(_msgSender);
                                            p.Position = packetin.ReadVector2();


                                            //server.ServerSender.SendMovementUpdate(server.EntitiesManager.GetPlayerByConnection(_msgSender));
                                            break;
                                        }
                                    case SharedLib.Constants.PacketType.EntityRotationUpdate:
                                        {
                                            server.EntitiesManager.GetPlayerByConnection(_msgSender).Rotation = packetin.ReadFloat();
                                           //server.ServerSender.SendRotationUpdate(server.EntitiesManager.GetPlayerByConnection(_msgSender));
                                            break;
                                        }
                                }
                                break;
                            }
                    }
                }


                
                long current = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond;
                if (current - last > Constants.UPDATE_RATIO)
                {
                    List<ServerChunk> chunks = new List<ServerChunk>();
                    if (server.EntitiesManager.EntitiesList.Where(p => p.Value.GetType() == typeof(ServerPlayer)).ToList().Count > 0)
                    {
                        foreach (var chunk in server.GameWorld.Chunks.Where(c=>c.Entities.Where(p=>p.GetType() == typeof(ServerPlayer)).ToList().Count > 0).ToList())
                        {
                            for (int x = chunk.X-1; x < chunk.X+2; x++)
                            {
                                for (int y = chunk.Y-1; y < chunk.Y+2; y++)
                                {
                                    ServerChunk currentChunk = server.GameWorld.Chunks.Where(c => c.X == x && c.Y == y).FirstOrDefault();
                                    if (currentChunk != null && !chunks.Contains(currentChunk))
                                        chunks.Add(currentChunk);
                                }
                            }

                        }
                    }

                    foreach (var item in chunks)
                    {
                        item.Update(current-last);
                    }

                    
                    last = current;
                }


            }
        }
    }
}
